package com.buddies.lottery.ui.lottery.detail;

import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;

import com.blankj.utilcode.util.ConvertUtils;
import com.blankj.utilcode.util.ToastUtils;
import com.buddies.lottery.App;
import com.buddies.lottery.R;
import com.buddies.lottery.base.BaseActivity;
import com.buddies.lottery.common.ConfigManager;
import com.buddies.lottery.common.UrlConstants;
import com.buddies.lottery.data.bean.BetItem;
import com.buddies.lottery.data.bean.Lottery;
import com.buddies.lottery.data.bean.LotteryTabOptions;
import com.buddies.lottery.data.resp.LotteryDetailResponse;
import com.buddies.lottery.data.resp.LotteryTabOptionsResponse;
import com.buddies.lottery.data.resp.PostBetResponse;
import com.buddies.lottery.ui.lottery.bet.period.LotteryPeriodBetRecordActivity;
import com.buddies.lottery.ui.lottery.history.LotteryHistoryActivity;
import com.buddies.lottery.ui.lottery.trend.LotteryTrendActivity;
import com.buddies.lottery.ui.pay.PayActivity;
import com.buddies.lottery.ui.web.WebActivity;
import com.buddies.lottery.utils.DateUtils;
import com.buddies.lottery.utils.LotteryUtils;
import com.buddies.lottery.utils.PopupWindowUtils;
import com.buddies.lottery.widget.CountDownTimerView;
import com.buddies.lottery.widget.DotView;
import com.buddies.lottery.widget.LotteryBetButton;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.google.gson.reflect.TypeToken;
import com.r0adkll.slidr.Slidr;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class LotteryDetailActivity extends BaseActivity<LotteryDetailContract.Presenter> implements LotteryDetailContract.View, View.OnClickListener, LotteryBetButton.OnBetButtonClickListener {

    protected Lottery mLottery;

    protected SwipeRefreshLayout mSwipeRefreshLayout;

    protected DotView mWinNumView;
    protected DotView mWinNumAnnotationView;
    protected TextView tvPeriod;
    protected TextView tvNextPeriod;
    protected TextView tvStatus;
    protected CountDownTimerView tvDuration;

    protected RecyclerView mRecyclerView;
    protected LotteryTabAdapter mTabAdapter;

    protected RecyclerView mOptionsRecyclerView;
    protected LotteryTabOptionsAdapter mTabOptionsAdapter;

    protected TextView tvBalance;
    protected TextView tvBet;
    protected EditText etMoney;
    protected LotteryBetButton mBetButton;
    protected View btnClear;
    protected View btnPost;

    protected Map<String, List<LotteryTabOptions>> mLotteryTabOptionsCache = new HashMap<>();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Slidr.attach(this, App.getSlidrConfig());
    }

    @Override
    protected int getLayoutId() {
        return R.layout.activity_lottery_detail;
    }

    @Override
    protected void initView() {
        setUp();
        findViewById(R.id.header_divider).setSelected(true);

        ImageView btnMore = findViewById(R.id.iv_action);
        btnMore.setImageResource(R.drawable.lottery_more_selector);
        btnMore.setVisibility(View.VISIBLE);
        btnMore.setOnClickListener(this);

        TextView btnBetRecord = findViewById(R.id.tv_action);
        btnBetRecord.setText("当期投注");
        btnBetRecord.setVisibility(View.VISIBLE);
        btnBetRecord.setOnClickListener(this);

        mSwipeRefreshLayout = findViewById(R.id.refresher);
        mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                forceRefresh();
            }
        });

        mWinNumView = findViewById(R.id.tv_win_num);
        mWinNumAnnotationView = findViewById(R.id.tv_win_num_annotation);
        tvPeriod = findViewById(R.id.tv_period);
        tvNextPeriod = findViewById(R.id.tv_next_period);
        tvStatus = findViewById(R.id.tv_status);
        tvDuration = findViewById(R.id.tv_duration);
        tvDuration.bindView(tvNextPeriod, tvStatus);
        tvDuration.setOnTimerListener(new CountDownTimerView.TimerListener() {
            @Override
            public void onTick(long millisUntilFinished) {
            }

            @Override
            public void onFinish() {
                // 请求下一轮
                mPresenter.loadLotteryDetail(mLottery.id);
            }
        });

        mRecyclerView = findViewById(R.id.recycler_view);
        mOptionsRecyclerView = findViewById(R.id.recycler_view_options);

        findViewById(R.id.ll_balance).setOnClickListener(this);
        tvBet = findViewById(R.id.tv_bet);
        tvBet.setSelected(true);

        etMoney = findViewById(R.id.et_money);
        etMoney.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
            }

            @Override
            public void afterTextChanged(Editable s) {
                notifyUpdateBetContent();
            }
        });

        tvBalance = findViewById(R.id.tv_balance);

        mBetButton = findViewById(R.id.btn_bet);
        mBetButton.setOnBetButtonClickListener(this);
        btnClear = findViewById(R.id.btn_clear);
        btnClear.setOnClickListener(this);
        btnPost = findViewById(R.id.btn_post);
        btnPost.setOnClickListener(this);
    }

    @Override
    protected void initData() {
        Intent intent = getIntent();
        if (intent != null) {
            mLottery = (Lottery) intent.getSerializableExtra("lottery");
        }

        if (mLottery == null || mLottery.id == 0) {
            finish();
            return;
        }

        setTitle(mLottery.name);

        mPresenter = new LotteryDetailPresenter(this);
        onUpdateBalance();

        mTabAdapter = new LotteryTabAdapter(mLottery.tabs);
        mTabAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
                if (position != mTabAdapter.getSelectedItem()) {
                    clearBetContent();

                    loadLotteryTabOptions(position, true);
                }
            }
        });

        mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
        mRecyclerView.setHasFixedSize(true);
        mRecyclerView.setAdapter(mTabAdapter);

        mTabOptionsAdapter = new LotteryTabOptionsAdapter(mLottery.id, null);
        mTabOptionsAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
                notifyUpdateBetContent();
            }
        });

        StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
        mOptionsRecyclerView.setLayoutManager(layoutManager);
        mOptionsRecyclerView.setHasFixedSize(true);
        mOptionsRecyclerView.setAdapter(mTabOptionsAdapter);

        forceRefresh();
    }

    private void clearBetContent() {
        mTabOptionsAdapter.clearSelectItems();
        etMoney.setText("");
        btnClear.setEnabled(false);
        notifyUpdateBetContent();
    }

    private void loadLotteryTabOptions(int position, boolean clearSelectedItems) {
        String lotteryTabQueryId = LotteryUtils.getLotteryTabQueryId(mLottery.id, mLottery.tabs.get(position).id);
        if (!mLotteryTabOptionsCache.containsKey(lotteryTabQueryId)) {
            // 加载本地缓存
            List<LotteryTabOptions> options = null;
            String json = App.getInstance().getACache().getAsString(lotteryTabQueryId);
            if (!TextUtils.isEmpty(json)) {
                options = App.getGson().fromJson(json, new TypeToken<List<LotteryTabOptions>>() {
                }.getType());
            }

            // 请求网络
            if (options == null || options.isEmpty()) {
                mPresenter.loadLotteryTabOptions(lotteryTabQueryId);
                showProgressDialog("正在加载");
            } else {
                List<LotteryTabOptions> items = flatMapOptions(lotteryTabQueryId, options);
                onUpdateLotteryTabOptions(items);
            }
        } else if (clearSelectedItems) {
            // 加载内存缓存
            List<LotteryTabOptions> items = mLotteryTabOptionsCache.get(lotteryTabQueryId);
            onUpdateLotteryTabOptions(items);
        }
    }

    private void forceRefresh() {
        if (mSwipeRefreshLayout != null) {
            mSwipeRefreshLayout.post(new Runnable() {
                @Override
                public void run() {
                    mSwipeRefreshLayout.setRefreshing(true);
                    mPresenter.loadLotteryDetail(mLottery.id);
                }
            });
        }
    }

    @Override
    public void onLotteryDetailLoaded(LotteryDetailResponse response) {
        mSwipeRefreshLayout.setRefreshing(false);
        Lottery lottery = response.lottery;
        if (lottery != null && lottery.id != 0) {
            if (lottery.prev != null) {
                mLottery.prev = lottery.prev;

                tvPeriod.setText(LotteryUtils.formatLotteryPeriod(lottery.prev.period));
                mWinNumView.setDots(lottery.id, lottery.prev.getWinNum());
                mWinNumAnnotationView.setDots(lottery.prev.getWinNumAnnotation());
            }

            if (lottery.rules != null) {
                mLottery.rules = lottery.rules;
            }

            if (lottery.next != null) {
                mLottery.next = lottery.next;

                tvNextPeriod.setText(LotteryUtils.formatLotteryNextPeriod(lottery.next.period_show));
                long delta = lottery.next.getOpenTimeDelta();
                tvDuration.setText(DateUtils.formatDuration(delta));
                tvDuration.setTime(mLottery, delta);
                if (delta > 0) {
                    tvDuration.startCountDown();
                }
            }

            if (lottery.next != null && lottery.prev != null &&
                    !TextUtils.isEmpty(lottery.prev.period) && !TextUtils.isEmpty(lottery.next.period) &&
                    Long.parseLong(lottery.next.period) > Long.parseLong(lottery.prev.period) + 1) {
                postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mPresenter.loadLotteryDetail(mLottery.id);
                    }
                }, 30000);
            }

            if (lottery.tabs != null) {
                mLottery.tabs = lottery.tabs;

                mTabAdapter.setNewData(mLottery.tabs);
                mTabAdapter.notifyDataSetChanged();
            }
        }

        loadLotteryTabOptions(mTabAdapter.getSelectedItem(), false);
    }

    @Override
    public void onLotteryTabOptionsLoaded(LotteryTabOptionsResponse response) {
        hideProgressDialog();

        List<LotteryTabOptions> options = response.options;
        if (options != null && !options.isEmpty()) {
            App.getInstance().getACache().put(response.key, App.getGson().toJson(options), 60 * 60); // 缓存1小时
        }

        List<LotteryTabOptions> items = flatMapOptions(response.key, options);
        onUpdateLotteryTabOptions(items);

        mPresenter.loadBalance();
    }

    private List<LotteryTabOptions> flatMapOptions(String key, List<LotteryTabOptions> options) {
        List<LotteryTabOptions> items = new ArrayList<>();
        if (options != null && !options.isEmpty()) {
            for (LotteryTabOptions parent : options) {
                items.add(parent);
                for (LotteryTabOptions child : parent.options) {
                    child.parent = parent;
                    items.add(child);
                }
            }
            mLotteryTabOptionsCache.put(key, items);
        }
        return items;
    }

    private void onUpdateLotteryTabOptions(List<LotteryTabOptions> items) {
        mTabOptionsAdapter.setNewData(items);
        mTabOptionsAdapter.notifyDataSetChanged();
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        switch (id) {
            case R.id.iv_action:
                showMoreOptions(v);
                break;
            case R.id.btn_history:
                PopupWindowUtils.getInstance().dismiss();
                LotteryHistoryActivity.launch(this, mLottery);
                break;
            case R.id.btn_trend:
                PopupWindowUtils.getInstance().dismiss();
                LotteryTrendActivity.launch(this, mLottery);
                break;
            case R.id.btn_help:
                PopupWindowUtils.getInstance().dismiss();
                WebActivity.launch(this, String.format(UrlConstants.HELP, mLottery.id), mLottery.name + "玩法");
                break;
            case R.id.tv_action:
                LotteryPeriodBetRecordActivity.launch(getActivity(), mLottery, mLottery.next.period);
                break;
            case R.id.ll_balance:
                PayActivity.launch(this);
            case R.id.btn_clear:
                clearBetContent();
                break;
            case R.id.btn_post:
                toPostBet();
                break;
        }
    }

    private void showMoreOptions(View anchor) {
        View view = getLayoutInflater().inflate(R.layout.popup_window_more_options, null);
        view.findViewById(R.id.btn_history).setOnClickListener(this);
        view.findViewById(R.id.btn_trend).setOnClickListener(this);
        view.findViewById(R.id.btn_help).setOnClickListener(this);

        int offsetY = ConvertUtils.dp2px(8);
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
            offsetY = -offsetY;
        }

        PopupWindowUtils.getInstance()
                .makePopupWindow(this, ConvertUtils.dp2px(140), ConvertUtils.dp2px(152), view, getResources().getColor(R.color.transparent))
                .showLocationWithAnimation(this, anchor, 0, offsetY, 0);
    }

    private void toPostBet() {
        btnPost.setEnabled(false);

        final int lotteryId = mLottery.id;
        final String period = mLottery.next.period;
        int tabId = mTabAdapter.getSelectedItemId();

        int sum = getInputMoney();

        final List<BetItem> betItems = new ArrayList<>();
        List<Integer> selectedOptions = mTabOptionsAdapter.getSelectedItems();
        int size = selectedOptions.size();
        List<String> items = new ArrayList<>();

        for (int i = 0; i < size; i++) {
            int position = selectedOptions.get(i);
            LotteryTabOptions option = mTabOptionsAdapter.getItem(position);
            if (option != null && option.parent != null) {
                betItems.add(BetItem.create(option.getBetId(tabId), sum));
                if (tabId == 1 && option.parent.id == 6) {
                    items.add(String.format("%s @%sx%s", option.name, option.odds, sum));
                } else {
                    items.add(String.format("%s %s @%sx%s", option.parent.name, option.name, option.odds, sum));
                }
            }
        }

        AlertDialog dialog = new AlertDialog.Builder(this)
                .setTitle(tvBet.getText().toString())
                .setItems(items.toArray(new String[]{}), null)
                .setNegativeButton("取消", null)
                .setPositiveButton("确认", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        mPresenter.postBet(lotteryId, period, betItems);
                        showProgressDialog("正在下注");
                    }
                })
                .setOnDismissListener(new DialogInterface.OnDismissListener() {
                    @Override
                    public void onDismiss(DialogInterface dialog) {
                        btnPost.setEnabled(true);
                    }
                })
                .create();
        dialog.setCanceledOnTouchOutside(false);
        dialog.show();
    }

    @Override
    public void onPostBetSuccess(PostBetResponse response) {
        hideProgressDialog();
        ToastUtils.showShort("投注成功");
        clearBetContent();
        onUpdateBalance();
    }

    private void notifyUpdateBetContent() {
        int sum = getInputMoney();
        int itemSize = mTabOptionsAdapter.getSelectedItems().size();
        int totalMoney = sum * itemSize;
        btnClear.setEnabled(etMoney.getText().length() > 0);
        tvBet.setText(String.format("共%s注%s元", itemSize, totalMoney));
        btnPost.setEnabled(totalMoney > 0);
    }

    @Override
    public void onUpdateBalance() {
        tvBalance.setText(LotteryUtils.formatBalance(ConfigManager.getInstance().getBalance()));
    }

    @Override
    public void onBetButtonClick(int betOptionId) {
        int money = getInputMoney();
        etMoney.setText(String.valueOf(money + betOptionId));
    }

    private int getInputMoney() {
        String money = etMoney.getText().toString();
        return !TextUtils.isEmpty(money) ? Integer.parseInt(money) : 0;
    }

    @Override
    public void onError(Throwable e) {
        super.onError(e);
        mSwipeRefreshLayout.setRefreshing(false);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mLotteryTabOptionsCache != null) {
            mLotteryTabOptionsCache.clear();
        }
    }

    public static void launch(Context context, Lottery lottery) {
        Intent intent = new Intent();
        intent.setClass(context, LotteryDetailActivity.class);
        intent.putExtra("lottery", lottery);
        context.startActivity(intent);
    }

}
